package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"regexp"

	"github.com/alecthomas/template"
)

func parseFile(path string) {
	//log.Printf("读取文件:%v\n", path)
	if data, err := ioutil.ReadFile(path); err != nil {
		log.Printf("读取文件失败:%v\n", err)
	} else {
		cs, _ := parseColl(data)
		for _, c := range cs {
			fmt.Println(formatColl(c))
		}
	}
}

var (
	regCollName = regexp.MustCompile(`^\s*//\s+@collname\s*([^\(]+)\(([^\)]+)\)\s*$`)
	regStart    = regexp.MustCompile(`^\s*type\s*(\S+)\s*struct\s*{`)
	regEnd      = regexp.MustCompile(`^}$`)
	regField    = regexp.MustCompile(`^\s*(\S+)\s*(\S+)\s*.?bson:\"([^,\"]+(?:,[^\"]+)?)\".?\s*//(.+)$`)
)

func parseColl(data []byte) (out []Coll, err error) {

	r := bufio.NewReader(bytes.NewReader(data))
	var coll Coll
	flag := 0
p:
	for {
		line, _, e1 := r.ReadLine()
		if e1 != nil {
			if e1 == io.EOF {
				return
			}
			log.Fatalf("读取失败:%v\n", e1)
		}
		switch flag {
		case 0:
			//log.Println(string(line))
			if regCollName.Match(line) {
				sub := regCollName.FindSubmatch(line)
				coll.Desc = string(sub[2])
				coll.Name = string(sub[1])
				//log.Println(coll)
				flag = 1
			}
		case 1:
			if regStart.Match(line) {
				flag = 2
			}
		case 2:
			if regEnd.Match(line) {
				flag = 0
				out = append(out, coll)
				coll = Coll{}
				continue p
			}
			if !regField.Match(line) {
				continue p
			}

			sub := regField.FindSubmatch(line)
			if len(sub) == 0 {
				continue p
			}
			f := Field{
				Name: string(sub[3]),
				Desc: string(sub[4]),
				Type: string(sub[2]),
			}
			coll.Fields = append(coll.Fields, f)
		default:
			log.Fatalln("解析错误不该执行到这里")
		}
	}
	return

}

// Coll 集合
type Coll struct {
	Name   string
	Desc   string
	Fields []Field
}

// Field 字段
type Field struct {
	Name   string
	Desc   string
	Type   string
	Remark string
}

var (
	regtype = map[string]string{
		"string":                     "字符串",
		"time.Time":                  "时间",
		"int":                        "整数",
		"int8":                       "整数(int8)",
		"int16":                      "整数(int16)",
		"int32":                      "整数(int32)",
		"int64":                      "整数(int64)",
		"uint":                       "整数(uint)",
		"uint8":                      "整数(uint8)",
		"uint16":                     "整数(uint16)",
		"uint32":                     "整数(uint32)",
		"uint64":                     "整数(uint64)",
		"bool":                       "布尔型",
		"[]string":                   "字符串数组",
		"cinteractiond.ITStatus":     "整数",
		"cinteractiond.ITMode":       "整数",
		"cinteractiond.RStatus":      "整数",
		"cinteractiond.IGStatus":     "整数",
		"cinteractiond.IGTargetType": "整数",
		"cgroupd.GStatus":            "整数",
		"cgroupd.GroupKind":          "整数",
		"ccolumnd.ColumnKind":        "整数",
	}
)

func type2name(t string) string {
	if n, ok := regtype[t]; ok {
		return n
	}
	return t
}

var collnameTplStr = `
## {{$.Coll.Desc}}({{$.Coll.Name}})

| 字段          | 中文说明   | 字段类型  | 备注        |
| ----------- | ------ | ----- | --------- |
{{range $.Coll.Fields}}| {{.Name}} | {{.Desc}} | {{t2n .Type}} | {{.Remark}} |
{{end}}

`
var (
	tpl = template.Must(template.New("").Funcs(template.FuncMap{
		"t2n": type2name,
	}).Parse(collnameTplStr))
)

func formatColl(d Coll) string {
	b := bytes.NewBuffer(nil)
	err := tpl.Execute(b, map[string]interface{}{
		"Coll": d,
	})
	if err != nil {
		fmt.Println(err)
	}
	return string(b.Bytes())
}
